package com.framework.core.beanfactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import com.framework.core.dispacher.ControlDispatcher;
import com.framework.core.domain.Control;
import com.framework.core.myannotation.MyAutowire;
import com.framework.core.myannotation.MyController;
import com.framework.core.myannotation.MyRepository;
import com.framework.core.myannotation.MyRequestMapping;
import com.framework.core.myannotation.MyService;
import com.framework.core.myexception.InitConfigException;
import com.framework.core.myexception.NoSuchComponentException;
import com.framework.core.sqlfactory.sqlmapperproxyfactory.SqlMapperProxy;
import com.framework.core.utils.PackageScanUtils;
import com.framework.core.utils.RequestMappingUtils;
import com.framework.core.utils.StringUtils;

/**
 * 组件扫描与属性注入要分开，避免没扫描到就已经开始注入
 * 
 */

public class MyBeanFactory {

	// 模拟controller(controller属性)
	private static Map<String, Control> controller = new HashMap<>();
	// controller组件
	private static Map<String, Object> controllerBeans = new HashMap<>();
	// 模拟ioc容器(service组件)
	private static Map<String, Object> serviceBeans = new HashMap<>();
	// 代理后的dao接口
	private static Map<String, Object> repositoryBeans = new HashMap<>();
	// 总ioc用于测试
	private static Map<String, Object> ioc = new HashMap<>();

	// 扫描所有组件
	public static void beanScanner(String path) throws ClassNotFoundException, IOException {

		System.out.println("开始扫描组件！");
		String[] paths = null;
		if (path.contains(",")) {
			paths = path.split(",");
		} else {
			paths = new String[] { path };
		}
		// 为什么先扫描组件然后注入属性：因为同时进行无法保证先后顺序，导致有些对象为空就注入了
		// 扫描组件
		for (int i = 0; i < paths.length; i++) {
			// 类对象
			Class<?>[] classs = PackageScanUtils.getClasses(paths[i]);
			// 扫描所有class并分类
			for (Class<?> clazz : classs) {
				try {
					// service组件
					if (clazz.isAnnotationPresent(MyService.class)) {
						String beanName = StringUtils.toLowerCaseFirstOne(clazz.getSimpleName()).replaceAll("Impl", "");
						serviceBeans.put(beanName, clazz.newInstance());
						System.out.println("扫描到service组件：" + beanName);
					} else if (clazz.isAnnotationPresent(MyController.class)) {
						// controller组件
						String beanName = StringUtils.toLowerCaseFirstOne(clazz.getSimpleName());
						controllerBeans.put(beanName, clazz.newInstance());
						System.out.println("扫描到Controller组件：" + beanName);
						// controller
						Method[] methods = clazz.getDeclaredMethods();
						for (Method method : methods) {
							Control control = null;
							if (method.isAnnotationPresent(MyRequestMapping.class)) {
								// 封装请求
								control = new Control();
								MyRequestMapping annotation = method.getAnnotation(MyRequestMapping.class);
								control.setClazz(clazz.getName());
								control.setName(annotation.value());
								control.setMethod(method.getName());
								controller.put(annotation.value(), control);
								System.out.println("扫描到controller：" + control);
							}
						}
					} else if (clazz.isAnnotationPresent(MyRepository.class)) {
						// repository组件
						String beanName = StringUtils.toLowerCaseFirstOne(clazz.getSimpleName()).replaceAll("Impl", "");
						// Object object = clazz.newInstance();

						// cglib代理
						// Object proxyInstance = new
						// SqlMapperCglibProxy().getProxyInstance(clazz);
						// java代理
						Object proxyInstance = new SqlMapperProxy().getProxyInstance(clazz);
						repositoryBeans.put(beanName, proxyInstance);
						System.out.println("扫描到repository组件：" + beanName);

					}

				} catch (Exception e) {
					throw new InitConfigException("初始化解析配置文件异常！");
				}
			}
		}

		RequestMappingUtils.getInstance().setController(controller);
		System.err.println(RequestMappingUtils.getInstance().getController());
		ioc.putAll(serviceBeans);
		ioc.putAll(repositoryBeans);
		ioc.putAll(controllerBeans);

		// 注入属性
		for (int i = 0; i < paths.length; i++) {
			// 类对象
			Class<?>[] classs = PackageScanUtils.getClasses(paths[i]);
			// 扫描所有class
			for (Class<?> clazz : classs) {
				if (clazz.isAnnotationPresent(MyService.class)) {
					Field[] declaredFields = clazz.getDeclaredFields();
					for (Field field : declaredFields) {
						if (field.isAnnotationPresent(MyAutowire.class)) {
							try {
								// 分隔
								String[] split = field.getGenericType().getTypeName().split("\\.");
								// 属性名
								String fieldName = StringUtils.toLowerCaseFirstOne(split[split.length - 1]);
								// 目标实例
								// Object obj = clazz.newInstance();
								String iocObjectName = StringUtils.toLowerCaseFirstOne(clazz.getSimpleName())
										.replaceAll("Impl", "");
								Object obj = getIocBean(iocObjectName);
								// 需要注入属性
								Object targetBean = getIocBean(fieldName);
								// 注入
								// ControlDispatcher.setTargetBeanBySet(clazz,
								// field.getType(), obj, targetBean);
								ControlDispatcher.setTargetBean(clazz, fieldName, obj, targetBean);
							} catch (Exception e) {
								e.printStackTrace();
								throw new InitConfigException("初始化解析配置文件异常！");
							}
						}
					}

				} else {
					Field[] declaredFields = clazz.getDeclaredFields();
					for (Field field : declaredFields) {
						if (field.isAnnotationPresent(MyAutowire.class)) {
							try {
								// 分隔
								String[] split = field.getGenericType().getTypeName().split("\\.");
								// 属性名
								String fieldName = StringUtils.toLowerCaseFirstOne(split[split.length - 1]);
								// 目标实例
								// Object obj = clazz.newInstance();
								String iocObjectName = StringUtils.toLowerCaseFirstOne(clazz.getSimpleName());
								Object obj = getIocBean(iocObjectName);
								// 需要注入属性
								Object targetBean = getIocBean(fieldName);
								// 注入
								// ControlDispatcher.setTargetBeanBySet(clazz,
								// field.getType(), obj, targetBean);
								ControlDispatcher.setTargetBean(clazz, fieldName, obj, targetBean);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}

				}
			}

		}
	}

	// 从beans集合取servicebean
	public static Object getBeanByName(String name) throws NoSuchComponentException {
		name = StringUtils.toLowerCaseFirstOne(name);
		if (serviceBeans.containsKey(name)) {
			return serviceBeans.get(name);
		} else {
			System.err.println("不存在：" + name + "service对象！");
			throw new NoSuchComponentException("不存在：" + name + "service对象！");
		}

	}

	// 从controllerBeans集合取controller
	public static Object getControllerByName(String name) throws NoSuchComponentException {

		if (controller.containsKey(name)) {
			return controller.get(name);
		} else {
			System.err.println("不存在：---" + name + "----controller！");
			throw new NoSuchComponentException("不存在：---" + name + "----requestMapping！");
		}

	}

	// 从controllerBeans集合取repository
	public static Object getRepositoryByName(String name) throws NoSuchComponentException {
		if (repositoryBeans.containsKey(name)) {
			return repositoryBeans.get(name);
		} else {
			System.err.println("不存在：" + name + "repository！");
			throw new NoSuchComponentException("不存在：" + name + "repository！");
		}

	}

	// 从ioc集合取Bean
	public static Object getIocBean(String name) throws NoSuchComponentException {
		if (ioc.containsKey(name)) {
			return ioc.get(name);
		} else {
			System.err.println("IOC不存在：" + name + "Bean！");
			throw new NoSuchComponentException("IOC不存在：" + name + "repository！");
		}
	}

	// 转换
	// private static Object converTo(Class<?> cls, Object object) {
	//
	// try {
	// return cls.cast(object);
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// return null;
	// }

}
